<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel='stylesheet' href='../rurple.css' type='text/css'>
<title>Fractions - part 1</title>
</head>
<body>
<h2 class="title">Fractions - part 1</h2>
<p>Would it not be nice if we could use Python to add and multiply fractions
just like we can do it with integers and other number types? Something
like:</p>
<pre>
&gt;&gt;&gt; a = 1/2
&gt;&gt;&gt; b = 1/4
&gt;&gt;&gt; <span class="keyword">print</span> a + b
3/4
</pre>
<p>Actually, we can teach Python to do something just like that! This is what
we are going to learn to do in this multi-part lesson. It is going to be a
rather long lesson, but we are going to learn a fair bit about some very
<i>private</i> parts of Python.</p>
<p>To help prevent having bugs in our program, we will proceed
systematically, adding only a little bit of new code at a time, using a three
step approach:</p>
<ol>
<li>Add some new functionality.</li>
<li>Check that it gives us the desired result, testing with <span class=
"pykeyword">print</span> statements.</li>
<li>Replace the <span class="pykeyword">print</span> statements by
<span class="pykeyword">assert</span> statements.</li>
</ol>
<p>Repeat these 3 steps as often as required! This is one example where it
make sense to repeat yourself!</p>
<!--=============================================-->
<hr width="50%">
<h3 class="section">Creating a new type</h3>
<p>Without further ado, here's the basic code to define a new "fraction"
type, and test it.</p>
<pre>
<span class='linenumber'>  1 </span><span class=
'keyword'>class</span> Fraction(object):
<span class='newlinenumber'>  2 </span>    <span class=
'keyword'>def</span> __init__(self, numerator, denominator=<span class=
'number'>1</span>):
<span class='linenumber'>  3 </span>        self.num = numerator
<span class='linenumber'>  4 </span>        self.denom = denominator
<span class='linenumber'>  5 </span>
<span class='linenumber'>  6 </span><span class=
'comment'>#== testing area below===
</span><span class='linenumber'>  7 </span>
<span class='linenumber'>  8 </span><span class=
'keyword'>if</span> __name__ ==<span class='string'> "__main__"</span>:
<span class='linenumber'>  9 </span>    a = Fraction(<span class=
'number'>1</span>,<span class='number'> 2</span>)
<span class='newlinenumber'> 10 </span>    b = Fraction(<span class=
'number'>3</span>)
<span class='linenumber'> 11 </span><span class=
'keyword'>    print</span> a.num, a.denom
<span class='linenumber'> 12 </span><span class=
'keyword'>    print</span> b.num, b.denom
<span class='linenumber'> 13 </span><span class='keyword'>    print</span> a
<span class='linenumber'> 14 </span><span class='keyword'>    print</span> b
</pre>
<p>By now, you should be able to understand what this code does on your own.
Notice the use of a named argument on line 2 so that we could pass a single
argument to <tt>Fraction()</tt> [as we did on line 10] and it would interpret
it as an integer (divided by 1). If we run it, we get the following
output:</p>
<pre>
1 2
3 1
&lt;__main__.Fraction object at 0x01530F30&gt;
&lt;__main__.Fraction object at 0x01530F50&gt;
</pre>
<p>The first two lines are as expected. However, the last two, when we try to
print the fractions <tt>a</tt> and <tt>b</tt> do not exactly look like what
we would want. Python does not know how we want the object to appear, so it
gives us something like the variable name it uses itself to keep track of
these two objects. To make Python print the fractions the way we want, we
need to tell it using one of the <i>private</i> methods.</p>
<!--=============================================-->
<hr width="50%">
<h3 class="section">Representing objects as strings</h3>
<p>To tell Python how we want objects to be printed, or represented as
strings, we use the function <tt>__str__()</tt>.</p>
<pre>
<span class='linenumber'>  1 </span><span class=
'keyword'>class</span> Fraction(object):
<span class='linenumber'>  2 </span>    <span class=
'keyword'>def</span> __init__(self, numerator, denominator=<span class=
'number'>1</span>):
<span class='linenumber'>  3 </span>        self.num = numerator
<span class='linenumber'>  4 </span>        self.denom = denominator
<span class='linenumber'>  5 </span>        
<span class='newlinenumber'>  6 </span>    <span class=
'keyword'>def</span> __str__(self):
<span class='newlinenumber'>  7 </span>        <span class=
'keyword'>return</span><span class=
'string'> "(%s/%s)"</span>%(self.num, self.denom)
<span class='linenumber'>  8 </span>
<span class='linenumber'>  9 </span><span class=
'comment'>#== testing area below===
</span><span class='linenumber'> 10 </span>
<span class='linenumber'> 11 </span><span class=
'keyword'>if</span> __name__ ==<span class='string'> "__main__"</span>:
<span class='linenumber'> 12 </span>    a = Fraction(<span class=
'number'>1</span>,<span class='number'> 2</span>)
<span class='linenumber'> 13 </span>    b = Fraction(<span class=
'number'>3</span>)
<span class='linenumber'> 14 </span><span class='keyword'>    print</span> a
<span class='linenumber'> 15 </span><span class='keyword'>    print</span> b
</pre>
<p>The result is:</p>
<pre>
(1/2)
(3/1)
</pre>
<!--=============================================-->
<hr width="50%">
<h3 class="try">Your turn</h3>
<p>Make a change to <tt>__str__()</tt> so that <span class=
"pykeyword">if</span> the denominator is 1, only the numerator is printed.
This means that, instead of having "<tt>(3/1)</tt>", we would simply have
"<tt>3</tt>"; however the result for "<tt>(1/2)</tt>" should be
unchanged.</p>
<!--=============================================-->
<hr width="50%">
<h3 class="section">Using <span class="pykeyword">assert</span></h3>
<p>Now that we have our desired result, we replace the <span class=
"pykeyword">print</span> statements by <span class="pykeyword">assert</span>
statements.</p>
<pre>
<span class='linenumber'>  1 </span><span class=
'keyword'>class</span> Fraction(object):
<span class='linenumber'>  2 </span>    <span class=
'keyword'>def</span> __init__(self, numerator, denominator=<span class=
'number'>1</span>):
<span class='linenumber'>  3 </span>        self.num = numerator
<span class='linenumber'>  4 </span>        self.denom = denominator
<span class='linenumber'>  5 </span>        
<span class='linenumber'>  6 </span>    <span class=
'keyword'>def</span> __str__(self):
<span class='linenumber'>  7 </span>        <span class=
'keyword'>return</span><span class=
'string'> "(%s/%s)"</span>%(self.num, self.denom)
<span class='linenumber'>  8 </span>
<span class='linenumber'>  9 </span><span class=
'comment'>#== testing area below===
</span><span class='linenumber'> 10 </span>
<span class='linenumber'> 11 </span><span class=
'keyword'>if</span> __name__ ==<span class='string'> "__main__"</span>:
<span class='linenumber'> 12 </span>    a = Fraction(<span class=
'number'>1</span>,<span class='number'> 2</span>)
<span class='linenumber'> 13 </span>    b = Fraction(<span class=
'number'>3</span>)
<span class='newlinenumber'> 14 </span><span class=
'keyword'>    assert</span> str(a) ==<span class='string'> "(1/2)"</span>
<span class='newlinenumber'> 15 </span><span class=
'keyword'>    assert</span> str(b) ==<span class='string'> "(3/1)"</span>
</pre>
<p>When we use assertions instead of printing, we need to compare the string
representation <tt>str()</tt> to the expected result. If you run this
program, it should not output anything; this is what we want! Note that I
still used the format with the denominator present, "<tt>(3/1)</tt>", and not
the format I asked you to define in the last exercise.</p>
<p>Next, we teach Python to multiply fractions!</p>
</body>
</html>
